#include <string.h>
#include <stdio.h>
#include "person.h"
#include "person_imp.h"

static int _person_count = 0;

static void _V_Say(ObjectPtr obj, const char* text) {
    Person *p = (Person*)obj;
    printf("%s | name is %s, age: %d\n", text, p->data._name, p->data._age);
}

static void _V_WorkForYear(ObjectPtr obj) {
    Person *p = (Person*)obj;
    p->data._age ++;

    puts("I have no job ...");
}

void Person_VFuncInit(Person_Func *vfunc) {
    vfunc->_Say = _V_Say;
    vfunc->_WorkForYear = _V_WorkForYear;
}

#define PARAM_LIST      PARAM_LIST_2
#define TYPE_PARAM_LIST C_TYPE_PARAM_LIST_2(const char*, int)
BASE_FUNC_DEFINE(Person, Base, OOP);
#undef TYPE_PARAM_LIST
#undef PARAM_LIST

void Person_Construct(ObjectPtr obj, const char* name, int age) {
    OOP_ASSERT(is_instance_of(obj, ClassID_Person));
    Base_Construct(obj);

    ++ _person_count;
    printf("person count: %d\n", _person_count);

    Person_Data *data = (Person_Data*)(obj+1);
    strcpy(data->_name, name);
    if (age > 0)
        data->_age = age;
}

void Person_Destruct(ObjectPtr obj) {
    OOP_ASSERT(is_instance_of(obj, ClassID_Person));

    -- _person_count;
    printf("person count: %d\n", _person_count);

    Base_Destruct(obj);
}

int Person_GetAge(ObjectPtr obj) {
    OOP_ASSERT(is_instance_of(obj, ClassID_Person));

    Person_Data *data = (Person_Data*)(obj+1);
    return data->_age;
}

const char* Person_GetName(ObjectPtr obj) {
    OOP_ASSERT(is_instance_of(obj, ClassID_Person));

    Person_Data *data = (Person_Data*)(obj+1);
    return data->_name;
}

#define PARAM_LIST      PARAM_LIST_0
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_0
VIRTUAL_FUNC_DEFINE(Person, WorkForYear);
#undef TYPE_PARAM_LIST
#undef PARAM_LIST

#define PARAM_LIST      PARAM_LIST_1
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_1(const char*)
VIRTUAL_FUNC_DEFINE(Person, Say);
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
